package net.spy.memcached;

import com.monkey.utils.MonkeyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.memcached.CacheExpire;

import java.util.*;


public class MemCache {
    private Logger log = LoggerFactory.getLogger(MemCache.class);
    private static final String DEFAULT_CACHE_ALL_KEY = "*";
    private static final int DEFAULT_MAX_EXPIRE_TIME = 2592000;

    private Set<String> keySet = new HashSet<>();
    private final String name;
    private final CacheExpire cacheExpire;
    private final MemcachedClientIF memcachedClient;

    public MemCache(String name, CacheExpire cacheExpire, MemcachedClientIF memcachedClient) {
        this.name = name;
        this.cacheExpire = cacheExpire;
        this.memcachedClient = memcachedClient;
    }

    public Object get(String key) {
        String memcachedKey = this.loadMemcachedKey(key);
        Object value = memcachedClient.get(memcachedKey);
        log.debug("MemCache get key [{}], hit {}, value [{}].", memcachedKey, value != null, value);
        if (MonkeyUtils.isNotEmpty(value)) {
            keySet.add(key);
        }
        return value;
    }

    public void put(String key, Object value) {
        if (value == null) {
            return;
        }
        int expirySeconds = loadCacheExpire(key);
        String memcachedKey = this.loadMemcachedKey(key);
        log.debug("MemCache set key [{}], value [{}], expirySeconds [{}] .", memcachedKey, value, expirySeconds);
        memcachedClient.set(memcachedKey, expirySeconds, value);
        keySet.add(key);
    }

    private int loadCacheExpire(String key) {
        if (MonkeyUtils.isEmpty(cacheExpire)) {
            return DEFAULT_MAX_EXPIRE_TIME;
        }
        Integer expire = cacheExpire.get(key);
        if (MonkeyUtils.isNotEmpty(expire)) {
            return expire;
        }
        Integer allExpire = cacheExpire.get(DEFAULT_CACHE_ALL_KEY);
        if (MonkeyUtils.isNotEmpty(allExpire)) {
            return allExpire;
        }
        return DEFAULT_MAX_EXPIRE_TIME;
    }

    public void clear() {
        for (String key : keySet) {
            String memcachedKey = this.loadMemcachedKey(key);
            memcachedClient.delete(memcachedKey);
        }
        log.debug("MemCache clear , keys: [{}]", keySet);
        keySet.clear();
    }

    public void delete(String key) {
        String memcachedKey = this.loadMemcachedKey(key);
        log.debug("MemCache delete key [{}].", memcachedKey);
        memcachedClient.delete(memcachedKey);
        keySet.remove(key);
    }

    public Set<String> getKeySet() {
        return keySet;
    }

    public int size() {
        return keySet.size();
    }

    @SuppressWarnings("unchecked")
    public Collection values() {
        List values = new ArrayList();
        for (String key : keySet) {
            values.add(get(key));
        }
        return values;
    }

    private String loadMemcachedKey(String key) {
        return name + ":" + key;
    }
}
